home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 15.1 KB | 539 lines | [TEXT/KAHL] |
- //------------------------- © 1994-1995 by James G. Stout --------------------------
- // File : cdefBar.c
- // Date : May 2, 1994
- // Author : Jim Stout
- // :
- // Purpose : A CDEF to implement a progress bar
- // :
- // : If you find a use for this, I'd love to know about it. Bug reports
- // : are always interesting.
- // :
- // : Internet : JimS@WRQ.COM(work hours, PST)
- // : AppleLink : WRQ (daily)
- // : CompuServe : 73240,2052 (weekly or so)
- // : AOL : JasG (weekly or so)
- // : eWorld : Jim Stout (weekly or so)
- //----------------------------------------------------------------------------------
- //#define _DEBUGCDEF 1 // comment out to build CDEF
-
- #include "fatCDEF.h"
-
- #include <Controls.h>
- #include <GestaltEqu.h>
- #include <LowMem.h>
- #include <Memory.h>
- #include <Palettes.h>
- #include <ToolUtils.h>
- #include <Types.h>
-
- #include "colorCDEF.h"
- #include "miscCDEF.h"
-
- #include "cdefBar.h"
-
-
- #ifdef _DEBUGCDEF
- pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param);
-
- pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param)
- #else
-
- //==================================================================================
- // CDEF entry point
- //==================================================================================
- pascal long main (short varCode, ControlHandle theCtl, short message, long param)
- #endif
- {
- cdefHdl hCdef;
- SignedByte cState, dState;
-
- #include "fatEntry.c"
-
- cState = HGetState((Handle)theCtl);
- HLock((Handle)theCtl);
- if((**theCtl).contrlData) {
- dState = HGetState((**theCtl).contrlData);
- HLock((**theCtl).contrlData);
- }
-
- switch(message) {
- case initCntl:
- hCdef = (cdefHdl)NewHandle(sizeof(cdefData));
- if(hCdef) {
- StuffHex(&(**hCdef).thePat,"\pF0783C1E0F87C3E1");
- (**theCtl).contrlData = (Handle)hCdef;
- dState = HGetState((**theCtl).contrlData);
- HLock((**theCtl).contrlData);
- }
- break;
- case dispCntl:
- if((**theCtl).contrlData) {
- HUnlock((**theCtl).contrlData);
- DisposeHandle((**theCtl).contrlData);
- (**theCtl).contrlData = 0;
- }
- break;
- case drawCntl:
- if((*theCtl)->contrlVis) {
- if(varCode & roundBar)
- drawRoundEndBar(theCtl, varCode);
- else
- drawRectBar(theCtl,varCode);
- }
- break;
- case calcCRgns:
- RectRgn((RgnHandle)(param & 0x7fffffffL), &(*theCtl)->contrlRect);
- break;
- case calcCntlRgn:
- case calcThumbRgn:
- RectRgn((RgnHandle)(param), &(*theCtl)->contrlRect);
- break;
- }
-
- if((**theCtl).contrlData)
- HSetState((**theCtl).contrlData, dState);
- HSetState((Handle)theCtl, cState);
-
-
- #include "fatExit.c"
-
- return (0L);
- }
-
- //==================================================================================
- // draw a simple rectangular progress bar
- //==================================================================================
-
- static void drawRectBar(ControlHandle theCtl, short varCode)
- {
- short pDepth,left,bottom,inx;
- long range,scale,filled;
- Byte holdByte;
- Rect r;
- Boolean inColor=false;
- RGBColor saveBack,saveFore;
- PenState penSt;
- cdefHdl hCdef;
-
- hCdef = (cdefHdl)(**theCtl).contrlData;
- if(!hCdef)
- return;
-
- if(!(varCode & barberPole)) {
- if((**theCtl).contrlMin == 0 && (**theCtl).contrlMax == 0)
- varCode ^= barberPole;
- }
-
- //----------------------------------------------------------------------------------
- // Initialize for drawing
- //----------------------------------------------------------------------------------
- r = (*theCtl)->contrlRect;
- InsetRect(&r,1,1);
-
- GetPenState(&penSt);
- PenSize(1,1);
- PenPat( (ConstPatternParam) "\xff\xff\xff\xff\xff\xff\xff\xff");
-
- pDepth = getPixDepth(&r);
- if(pDepth > 2) {
- saveColors(&saveFore, &saveBack);
- inColor = true;
- }
-
- //----------------------------------------------------------------------------------
- // frame the progress bar
- //----------------------------------------------------------------------------------
-
- FrameRect(&r);
- if(inColor)
- frame3DRect(&r);
- InsetRect(&r,1,1);
-
- if(varCode & vertBar)
- scale = r.bottom-r.top;
- else
- scale = r.right-r.left;
-
- //----------------------------------------------------------------------------------
- // draw a "barber" pole status bar
- //----------------------------------------------------------------------------------
-
- if(varCode & barberPole) {
- if(inColor) {
- setPartColor(theCtl, cTingeLight, true);
- setPartColor(theCtl, cFillPatColor, false);
- }
-
- PenPat(&(**hCdef).thePat);
- PaintRect(&r);
-
- //----------------------------------------------------------------------------------
- // rotate the barber pole pattern
- //----------------------------------------------------------------------------------
-
- holdByte = (**hCdef).thePat.pat[0];
- for(inx=0; inx<7; inx++)
- (**hCdef).thePat.pat[inx] = (**hCdef).thePat.pat[inx+1];
- (**hCdef).thePat.pat[7] = holdByte;
- }
-
- //----------------------------------------------------------------------------------
- // draw a regular "thermometer style" status bar
- //----------------------------------------------------------------------------------
-
- else {
-
- //----------------------------------------------------------------------------------
- // calculate "filled" portion of progress bar
- //----------------------------------------------------------------------------------
-
- range = (*theCtl)->contrlMax - (*theCtl)->contrlMin;
- if(range == 0)
- range = 1;
- filled = (*theCtl)->contrlValue * scale / range;
-
- //----------------------------------------------------------------------------------
- // draw the "un-filled" portion of the progress bar
- //----------------------------------------------------------------------------------
-
- if(varCode & vertBar) {
- bottom = r.bottom;
- r.bottom = r.bottom-filled; // top portion
- }
- else {
- left = r.left;
- r.left = r.left+filled; // right portion
- }
- if(inColor) {
- setPartColor(theCtl, cTingeLight, false);
- }
- PenPat( (ConstPatternParam) "\x00\x00\x00\x00\x00\x00\x00\x00");
- PaintRect(&r); // erase to bg color
-
- //----------------------------------------------------------------------------------
- // draw the "filled" portion of the progress bar
- //----------------------------------------------------------------------------------
-
- if(varCode & vertBar) {
- r.bottom = bottom;
- r.top = r.bottom-filled; // bottom portion
- }
- else {
- r.left = left;
- r.right = r.left+filled; // left portion
- }
- if(inColor) {
- setPartColor(theCtl, cFillPatColor, false);
- PaintRect(&r);
- }
- else {
- PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
- PaintRect(&r);
- }
- }
- if(inColor)
- restoreColors(&saveFore, &saveBack);
- SetPenState(&penSt);
- }
-
- //==================================================================================
- // draw an round ended progress bar
- //==================================================================================
-
- static void drawRoundEndBar(ControlHandle theCtl, short varCode)
- {
- short pDepth, diameter, inx;
- Byte holdByte;
- long range, scale, filled, unfilled, max;
- Rect r, rFill, rNoFill, rClip;
- Boolean inColor=false;
- RGBColor saveBack, saveFore;
- PenState penSt;
- RgnHandle c;
- cdefHdl hCdef;
-
- hCdef = (cdefHdl)(**theCtl).contrlData;
- if(!hCdef)
- return;
-
- if(!(varCode & barberPole)) {
- if((**theCtl).contrlMin == 0 && (**theCtl).contrlMax == 0)
- varCode ^= barberPole;
- }
-
- //----------------------------------------------------------------------------------
- // Initialize for drawing
- //----------------------------------------------------------------------------------
- rFill = (*theCtl)->contrlRect;
- InsetRect(&rFill,1,1);
-
- GetPenState(&penSt);
- PenSize(1,1);
- PenPat( (ConstPatternParam) "\xff\xff\xff\xff\xff\xff\xff\xff");
-
- pDepth = getPixDepth(&rFill);
- if(pDepth > 2) {
- saveColors(&saveFore, &saveBack);
- inColor = true;
- }
-
- c = NewRgn();
- GetClip(c);
-
- //----------------------------------------------------------------------------------
- // draw the frame of the progress bar - 3D look
- //----------------------------------------------------------------------------------
-
- if(varCode & vertBar)
- diameter = rFill.right - rFill.left;
- else
- diameter = rFill.bottom - rFill.top;
-
- frame3DRoundEndBar(&rFill, diameter, inColor);
- InsetRect(&rFill, diameter/5, diameter/5);
- r = rNoFill = rFill;
-
- //----------------------------------------------------------------------------------
- // draw a "barber" pole status bar
- //----------------------------------------------------------------------------------
-
- if(varCode & barberPole) {
- if(inColor) {
- setPartColor(theCtl, cTingeLight, true);
- setPartColor(theCtl, cFillPatColor, false);
- }
- PenPat(&(**hCdef).thePat);
- PaintRoundRect(&rFill, diameter, diameter);
-
- //----------------------------------------------------------------------------------
- // rotate the barber pole pattern
- //----------------------------------------------------------------------------------
-
- holdByte = (**hCdef).thePat.pat[0];
- for(inx=0; inx<7; inx++)
- (**hCdef).thePat.pat[inx] = (**hCdef).thePat.pat[inx+1];
- (**hCdef).thePat.pat[7] = holdByte;
- }
-
- //----------------------------------------------------------------------------------
- // draw a regular "thermometer style" status bar
- //----------------------------------------------------------------------------------
-
- else {
-
- //----------------------------------------------------------------------------------
- // calculate "filled" portion of progress bar
- //----------------------------------------------------------------------------------
-
- if(varCode & vertBar) {
- diameter = rFill.right - rFill.left;
- scale = rFill.bottom-rFill.top;
- }
- else {
- diameter = rFill.bottom - rFill.top;
- scale = rFill.right-rFill.left;
- }
-
- range = (*theCtl)->contrlMax - (*theCtl)->contrlMin;
- if(range == 0)
- range = 1;
- filled = (*theCtl)->contrlValue * scale / range;
- max = (*theCtl)->contrlMax * scale / range;
- unfilled = max-filled;
-
- //----------------------------------------------------------------------------------
- // set up the rects for the "filled" and "unfilled" areas of the bar
- //----------------------------------------------------------------------------------
-
- if(varCode & vertBar) {
- if(unfilled < diameter) {
- rNoFill.bottom = rNoFill.top+diameter+diameter/2;
- }
- else {
- rNoFill.bottom = rNoFill.top+unfilled+diameter/2;
- if(filled < diameter/2)
- rNoFill.bottom = r.bottom;
- }
-
- if(filled < diameter) {
- rFill.top = rFill.bottom-diameter-diameter/2;
- }
- else {
- rFill.top = rFill.bottom-filled-diameter/2;
- if(unfilled < diameter/2)
- rFill.top = r.top;
- }
- rClip = rNoFill;
- rClip.bottom = rClip.top+unfilled;
- }
- else {
- if(unfilled < diameter) {
- rNoFill.left = rNoFill.right-diameter-diameter/2;
- }
- else {
- rNoFill.left = rNoFill.right-unfilled-diameter/2;
- if(filled < diameter/2)
- rNoFill.left = r.left;
- }
-
- if(filled < diameter) {
- rFill.right = rFill.left+diameter+diameter/2;
- }
- else {
- rFill.right = rFill.left+filled+diameter/2;
- if(unfilled < diameter/2)
- rFill.right = r.right;
- }
- rClip = rNoFill;
- rClip.left = rClip.right-unfilled;
- }
-
- //----------------------------------------------------------------------------------
- // draw the "unfilled" portion of the progress bar
- //----------------------------------------------------------------------------------
-
- if(inColor) {
- setPartColor(theCtl, cTingeLight, false);
- }
- ClipRect(&rClip);
- PenPat( (ConstPatternParam) "\x00\x00\x00\x00\x00\x00\x00\x00");
- PaintRoundRect(&rNoFill, diameter, diameter);
-
- //----------------------------------------------------------------------------------
- // draw the "filled" portion of the progress bar
- //----------------------------------------------------------------------------------
-
- rClip = rFill;
- if(varCode & vertBar)
- rClip.top = rClip.bottom-filled;
- else
- rClip.right = rClip.left+filled;
-
- ClipRect(&rClip);
-
- if(inColor) {
- setPartColor(theCtl, cFillPatColor, false);
- PaintRoundRect(&rFill, diameter, diameter);
- }
- else { // in b&w, draw "filled"
- GetPenState(&penSt); // portion in a gray pattern
- PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
- PaintRoundRect(&rFill, diameter, diameter);
- SetPenState(&penSt);
- FrameRoundRect(&rFill, diameter, diameter);
- }
-
- PenPat( (ConstPatternParam) "\xff\xff\xff\xff\xff\xff\xff\xff");
- //----------------------------------------------------------------------------------
- // make it look rounded
- //----------------------------------------------------------------------------------
-
- if(inColor) {
- setPartColor(theCtl, cTingeLight, true);
- if(varCode & vertBar) {
- MoveTo(r.left+diameter/4, r.bottom-diameter/2);
- LineTo(r.left+diameter/4, r.top+diameter/2);
- }
- else {
- MoveTo(r.left+diameter/2, r.top+diameter/4);
- LineTo(r.right-diameter/2, r.top+diameter/4);
- }
- }
- }
- SetClip(c);
- DisposeRgn(c);
-
- if(inColor)
- restoreColors(&saveFore, &saveBack);
- else
- ForeColor(blackColor);
- SetPenState(&penSt);
- }
-
- //==================================================================================
- // frame a rect with an inset 3D effect by drawing right & bottom edges in white
- // and left & top in gray.
- //==================================================================================
- static void frame3DRect(Rect *r)
- {
- RGBColor rgbA = {0xAAAA,0xAAAA,0xAAAA},saveFore;
-
-
-
- GetForeColor(&saveFore);
- RGBForeColor(&rgbA);
-
- MoveTo((*r).left-1,(*r).bottom);
- LineTo((*r).left-1,(*r).top-1);
- LineTo((*r).right,(*r).top-1);
-
- ForeColor(whiteColor);
- Move(0,1);
- LineTo((*r).right,(*r).bottom);
- LineTo((*r).left,(*r).bottom);
-
- RGBForeColor(&saveFore);
- }
-
- //==================================================================================
- // draw a bar with rounded ends, with a 3D effect by drawing the frame in white
- // from 45-225 & black from 225-45 degrees.
- //==================================================================================
- static void frame3DRoundEndBar(Rect *rr, short diameter, Boolean inColor)
- {
- Rect r,r2;
- Boolean vert=false;
- RGBColor rgbBack;
-
- if(inColor) {
- GetBackColor(&rgbBack);
- if(rgbBack.red == 65535 &&
- rgbBack.green == 65535 &&
- rgbBack.blue == 65535)
- inColor = false;
- }
- r = r2 = *rr;
-
- if((r.right-r.left) < (r.bottom-r.top))
- vert = true;
-
- if(vert) {
- r2.bottom = r2.top + diameter;
- if(inColor)
- ForeColor(whiteColor);
- FrameArc(&r2, 45, 45);
- MoveTo(r.right-1, r.top+diameter/2);
- LineTo(r.right-1, r.bottom-diameter/2);
- r2.bottom = r.bottom;
- r2.top = r.bottom-diameter;
- FrameArc(&r2, 90, 135);
-
- ForeColor(blackColor);
- FrameArc(&r2, 225, 45);
- MoveTo(r.left, r.bottom-diameter/2);
- LineTo(r.left, r.top+diameter/2);
- r2.top = r.top;
- r2.bottom = r2.top+diameter;
- FrameArc(&r2, 270, 135);
- }
- else {
- if(inColor)
- ForeColor(whiteColor);
- r2.left = r2.right - diameter;
- FrameArc(&r2, 45, 135);
- MoveTo(r.right-diameter/2, r.bottom-1);
- LineTo(r.left+diameter/2, r.bottom-1);
- r2.left=r.left;
- r2.right=r.left+diameter;
- FrameArc(&r2, 180, 45);
-
- ForeColor(blackColor);
- FrameArc(&r2, 225, 135);
- MoveTo(r.left+diameter/2, r.top);
- LineTo(r.right-diameter/2, r.top);
- r2.right=r.right;
- r2.left=r.right-diameter;
- FrameArc(&r2, 0, 45);
- }
- }
-